﻿using System;
using Microsoft.SPOT;

using GT = Gadgeteer;
using GTM = Gadgeteer.Modules;
using GTI = Gadgeteer.Interfaces;

namespace Gadgeteer.Modules.Sytech
{
    //Version 1.02
    
    /// <summary>
    /// A LCDTOUCH4_3 Gadgeteer module
    /// </summary>
    public class LCDTouch : GTM.Module.DisplayModule
    {
        
        /// <summary>
        /// Property
        /// Return if the current module supports a touch screen
        /// </summary>
        public bool HasTouch { private set; get; } 

        private const uint DISPLAY_WIDTH = 480;
        private const uint DISPLAY_HEIGHT = 272;
       
        /// <summary>
        /// Constructor used if touch option not used
        /// </summary>
        /// <param name="redSocketNumber">skt number for Red</param>
        /// <param name="greenSocketNumber">skt number for Blue</param>
        /// <param name="blueSocketNumber">skt number for touch</param>
        public LCDTouch(int redSocketNumber, int greenSocketNumber, int blueSocketNumber):this(redSocketNumber,greenSocketNumber,blueSocketNumber,Socket.Unused)
        {
        }

        // Note: A constructor summary is auto-generated by the doc builder.
        /// <summary></summary>
        /// <param name="redSocketNumber">skt number for Red</param>
        /// <param name="greenSocketNumber">skt number for Green</param>
        /// <param name="blueSocketNumber">skt number for Blue</param>
        /// <param name="optTouchSocketNumber">skt number for touch</param>
        public LCDTouch(int redSocketNumber, int greenSocketNumber,int blueSocketNumber, int optTouchSocketNumber):base(WPFRenderOptions.Ignore)
        {
            // validate and intialise the sockets
            InitLCDSocket(redSocketNumber, 'R');
            InitLCDSocket(greenSocketNumber, 'G');
            InitLCDSocket(blueSocketNumber, 'B');

            // config the lcd settings
            ConfigureLCD();

            if ( optTouchSocketNumber != Socket.Unused)
            {
                InitTouchSocket(optTouchSocketNumber);
            }
            else
            {
                HasTouch = false;
            }
      
        }

        private bool m_touchInitialised = false;

        /// <summary>
        /// Initialise the touch controller.
        /// This will return if the touch is initialised and available
        /// </summary>
        /// <returns>true if touch initialised and avaialble
        ///           false if no touch</returns>
        public bool InitTouch()
        {
            if (HasTouch && !m_touchInitialised)
            {
                Microsoft.SPOT.Touch.Touch.Initialize(Application.Current);
                m_touchInitialised = true;  // only allow this once
            }
            return HasTouch;
        }

        /// <summary>
        /// Initialise the Touch Socket
        /// </summary>
        /// <param name="socketNumber">Touch socket number</param>
        private void InitTouchSocket(int socketNumber)
        {
            Socket socket = Socket.GetSocket(socketNumber, true, this, null);
            socket.EnsureTypeIsSupported('T', this);

            HasTouch = true;
            socket.ReservePin(Socket.Pin.Four, this);
            socket.ReservePin(Socket.Pin.Five, this);
            socket.ReservePin(Socket.Pin.Six, this);
            socket.ReservePin(Socket.Pin.Seven, this);

            // Now enable the Touch Controller
         //   Microsoft.SPOT.Touch.Touch.Initialize(Application.Current);

            //we have a touch capability - so initialise here
            InitTouch();

        }

        /// <summary>
        /// Validate and reserve the pins each R,G,B socket
        /// </summary>
        /// <param name="socketNumber"></param>
        /// <param name="socketType">the socket identifier</param>
        private void InitLCDSocket(int socketNumber, char socketType)
        {
            Socket socket = Socket.GetSocket(socketNumber, true, this, null);

            socket.EnsureTypeIsSupported(socketType,this);

            // now reserve the pins
            socket.ReservePin(Socket.Pin.Three, this);   
            socket.ReservePin(Socket.Pin.Four, this);  
            socket.ReservePin(Socket.Pin.Five, this);  
            socket.ReservePin(Socket.Pin.Six, this);
            socket.ReservePin(Socket.Pin.Seven, this);
            socket.ReservePin(Socket.Pin.Eight, this);
            socket.ReservePin(Socket.Pin.Nine, this);
             

        }

        /// <summary>
        /// Set up configuration for this lcd
        /// </summary>
        private void ConfigureLCD()
        {
            Mainboard.LCDConfiguration lcdConfig = new Mainboard.LCDConfiguration();

            lcdConfig.LCDControllerEnabled = true;

            lcdConfig.Width = Width;
            lcdConfig.Height = Height;

            // Only use if needed, see documentation.
            lcdConfig.PriorityEnable = false;

            lcdConfig.OutputEnableIsFixed = false;
            lcdConfig.OutputEnablePolarity = true;

            lcdConfig.HorizontalSyncPolarity = false;
            lcdConfig.VerticalSyncPolarity = false;
            lcdConfig.PixelPolarity = true;

            lcdConfig.HorizontalSyncPulseWidth = 40;
            lcdConfig.HorizontalBackPorch = 3;
            lcdConfig.HorizontalFrontPorch = 2;
            lcdConfig.VerticalSyncPulseWidth = 10;
            lcdConfig.VerticalBackPorch = 2;
            lcdConfig.VerticalFrontPorch = 3;

            lcdConfig.PixelClockDivider = 8;

            // Set configs
            DisplayModule.SetLCDConfig(lcdConfig);
        }

        

        

        
       
        
 

        #region Overrides of DisplayModule

        /// <summary>
        /// When overridden in a derived class, renders display data on the display device.
        /// </summary>
        /// <param name="bitmap">The <see cref="Microsoft.SPOT.Bitmap"/> object to render on the display.</param>
        protected override void Paint(Bitmap bitmap)
        {
            try
            {
                bitmap.Flush();
            }
            catch
            {
                ErrorPrint("Painting error");
            }
        }

        /// <summary>
        /// When overridden in a derived class, gets the width of the display module.
        /// </summary>
        public override uint Width
        {
            get { return DISPLAY_WIDTH; }
        }

        /// <summary>
        /// When overridden in a derived class, gets the height of the display module.
        /// </summary>
        public override uint Height
        {
            get { return DISPLAY_HEIGHT; }
        }

        #endregion
    }
}
